package context

import (
	"errors"
	"fmt"
	"reflect"
	"sync"
)

var sLock = sync.RWMutex{}

func (context *Configuration) BeanOf(name string, f func() (interface{}, error)) (interface{}, error) {

	sLock.RLock()

	if bean, ok := context.services[name]; ok {
		sLock.RUnlock()
		return bean, nil
	}

	sLock.RUnlock()

	if f != nil {

		bean, err := f()

		sLock.Lock()
		defer sLock.Unlock()

		context.services[name] = bean
		return bean, err
	}

	return nil, errors.New("no bean & default func")
}

func (context *Configuration) Beans() map[string]interface{} {
	return config.services
}

func (context *Configuration) Register(bean interface{}) {

	sLock.Lock()
	defer sLock.Unlock()

	name := reflect.TypeOf(bean).String()
	context.services[name] = bean
}

func (context *Configuration) RegisterForName(name string, bean interface{}) {

	sLock.Lock()
	defer sLock.Unlock()

	context.services[name] = bean
}

func (context *Configuration) MustServiceOfType(bean interface{}) interface{} {

	tp := reflect.TypeOf(bean)

	t := tp.String()

	sLock.RLock()
	defer sLock.RUnlock()

	if s, ok := context.services[t]; !ok {
		panic(fmt.Sprintf("未注册此服务 %s", t))
	} else {
		return s
	}
}
